package org.tabletopmachine.states.mainmenu;

import org.tabletopmachine.Game;
import org.tabletopmachine.IMenu;
import org.tabletopmachine.basics.Parsing;
import org.tabletopmachine.match.*;
import org.tabletopmachine.match.unit.*;

import de.matthiasmann.twl.*;
import de.matthiasmann.twl.ColumnLayout.Row;
import de.matthiasmann.twl.EditField.Callback;
import de.matthiasmann.twl.ListBox.CallbackReason;
import de.matthiasmann.twl.model.SimpleChangableListModel;

public class ManageArmyMenu extends Widget implements IMenu {
	private final MainMenuState _mMS;
	private final DialogLayout _manageArmyPanel;
	private final ColumnLayout _unitPropertiesPanel;
	private final Label _nameLabel;
	private final ListBox<Unit> _unitsListBox;
	private final Button _addButton, _remButton, _acceptButton, _cancelButton;
	private final Player _player;
	private final EditField _nameEF, _modelsEF, _filesEF, _ranksEF;
	private final ToggleButton _championTB, _standardTB, _musicianTB;
	private final ComboBox<TroopType> _troopTypeCB;
	private final ComboBox<ModelBase> _baseSizeCB;
	private final ComboBox<Weapon> _weaponsCB;
	private final Button _saveButton;

	public ManageArmyMenu(MainMenuState state, Player player) {

		_mMS = state;
		_player = player;
		_manageArmyPanel = new DialogLayout();
		_unitPropertiesPanel = new ColumnLayout();

		_nameLabel = new Label();
		_unitsListBox = new ListBox<Unit>();
		SimpleChangableListModel<Unit> UnitModel = new SimpleChangableListModel<Unit>();
		_unitsListBox.setModel(UnitModel);
		_unitsListBox.addCallback(new CallbackWithReason<ListBox.CallbackReason>() {

			@Override
			public void callback(CallbackReason cbreason) {
				if (cbreason == CallbackReason.SET_SELECTED || cbreason == CallbackReason.MOUSE_CLICK) {

					UnitSelected(_unitsListBox.getModel().getEntry(_unitsListBox.getSelected()));
				}
			}
		});

		_addButton = new Button("Add");
		_remButton = new Button("Remove");
		_acceptButton = new Button("Accept");
		_cancelButton = new Button("Cancel");

		_saveButton = new Button("Save");
		_saveButton.addCallback(new Runnable() {

			@Override
			public void run() {
				saveUnitChanges();
			}

		});
		_cancelButton.addCallback(new Runnable() {
			public void run() {
				cancel();
			}
		});
		_acceptButton.addCallback(new Runnable() {
			public void run() {
				accept();
			}
		});
		_addButton.addCallback(new Runnable() {
			public void run() {
				add();
			}
		});
		_remButton.addCallback(new Runnable() {
			public void run() {
				remove();
			}
		});

		_nameEF = new EditField();

		_troopTypeCB = new ComboBox<TroopType>();
		_baseSizeCB = new ComboBox<ModelBase>();
		_weaponsCB = new ComboBox<Weapon>();
		initComboBoxes();

		_modelsEF = new EditField();

		_filesEF = new EditField();

		Callback ModelsFilesCallback = new Callback() {

			@Override
			public void callback(int arg0) {
				if (update(_modelsEF) & update(_filesEF)) {
					_ranksEF.setErrorMessage(null);
					updateRanks();
				} else {
					_ranksEF.setText("Does not compute!!!");
					_ranksEF.setErrorMessage("Could not compute ranks!");
				}
			}

			private boolean update(EditField editField) {
				Integer NewValue = Parsing.tryParse(editField.getText());
				if (NewValue == null) {
					editField.setErrorMessage("Must be a number!");
					return false;
				} else {
					editField.setErrorMessage(null);
					return true;
				}
			}
		};
		_modelsEF.addCallback(ModelsFilesCallback);
		_filesEF.addCallback(ModelsFilesCallback);
		_ranksEF = new EditField();
		_ranksEF.setEnabled(false);
		_ranksEF.setTooltipContent("Is computed by model count and files");
		_championTB = new ToggleButton("Champion");
		_standardTB = new ToggleButton("Standard Bearer");
		_musicianTB = new ToggleButton("Musician");

		DialogLayout.Group VerticalLeftColumn = _manageArmyPanel.createSequentialGroup().addWidgets(_nameLabel, _unitsListBox)
				.addGroup(_manageArmyPanel.createParallelGroup(_remButton, _addButton)).addGap(20)
				.addGroup(_manageArmyPanel.createParallelGroup(_cancelButton, _acceptButton));
		DialogLayout.Group HorizontalLeftColumn = _manageArmyPanel.createParallelGroup().addWidgets(_nameLabel, _unitsListBox)
				.addGroup(_manageArmyPanel.createSequentialGroup(_remButton, _addButton)).addGap(20)
				.addGroup(_manageArmyPanel.createSequentialGroup(_cancelButton, _acceptButton));

		Row row1 = _unitPropertiesPanel.addRow("NameL", "NameEF");
		row1.addWithLabel("Name", _nameEF);

		Row row2 = _unitPropertiesPanel.addRow("col1", "col2", "col3", "col4", "col5");
		row2.addWithLabel("TroopType", _troopTypeCB);
		row2.addWithLabel("Models", _modelsEF);
		row2.add(_championTB);

		Row row3 = _unitPropertiesPanel.addRow("col1", "col2", "col3", "col4", "col5");
		row3.addWithLabel("Base", _baseSizeCB);
		row3.addWithLabel("Files", _filesEF);
		row3.add(_standardTB);

		Row row4 = _unitPropertiesPanel.addRow("col1", "col2", "col3", "col4", "col5");
		row4.addWithLabel("Weapon", _weaponsCB);
		row4.addWithLabel("Ranks", _ranksEF);
		row4.add(_musicianTB);

		Row row5 = _unitPropertiesPanel.addRow("col1");
		row5.add(_saveButton);
		
		_unitPropertiesPanel.addDefaultGaps();
		_unitPropertiesPanel.setEnabled(false);
		_manageArmyPanel.setHorizontalGroup(_manageArmyPanel.createSequentialGroup().addGroup(HorizontalLeftColumn).addWidget(_unitPropertiesPanel));
		_manageArmyPanel.setVerticalGroup(_manageArmyPanel.createParallelGroup().addGroup(VerticalLeftColumn).addWidget(_unitPropertiesPanel));

		add(_manageArmyPanel);
	}

	protected void updateRanks() {
		if (Parsing.tryParse(_filesEF.getText()) != null && Parsing.tryParse(_modelsEF.getText()) != null)
			_ranksEF.setText("" + Unit.computeRanks(Integer.parseInt(_modelsEF.getText()), Integer.parseInt(_filesEF.getText())));
	}

	private void saveUnitChanges() {
		Unit sel = _unitsListBox.getModel().getEntry(_unitsListBox.getSelected());
		sel.setName(_nameEF.getText());
		sel.setModels(Integer.parseInt(_modelsEF.getText()));
		sel.setFiles(Integer.parseInt(_filesEF.getText()));
		sel.setWeapon(_weaponsCB.getModel().getEntry(_weaponsCB.getSelected()));
		sel.setTroopType(_troopTypeCB.getModel().getEntry(_troopTypeCB.getSelected()));
		sel.setBase(_baseSizeCB.getModel().getEntry(_baseSizeCB.getSelected()));
		sel.setMusician(_musicianTB.isActive());
		sel.setChampion(_championTB.isActive());
		sel.setStandardbearer(_standardTB.isActive());
		_unitsListBox.invalidateLayout();
	}

	private void UnitSelected(Unit entry) {
		_unitPropertiesPanel.setEnabled(true);
		_nameEF.setText(entry.getName());
		_modelsEF.setText("" + entry.getModels());
		_filesEF.setText("" + entry.getFiles());
		_ranksEF.setText("" + entry.getRanks());
		_championTB.setActive(entry.hasChampion());
		_standardTB.setActive(entry.hasStandardbearer());
		_musicianTB.setActive(entry.hasMusician());
		for (int i = 0; i < _weaponsCB.getModel().getNumEntries(); i++) {
			if (_weaponsCB.getModel().getEntry(i).getName() == entry.getWeapon().getName())
				_weaponsCB.setSelected(i);
		}

		for (int i = 0; i < _troopTypeCB.getModel().getNumEntries(); i++) {
			if (_troopTypeCB.getModel().getEntry(i).getName() == entry.getTroopType().getName())
				_troopTypeCB.setSelected(i);
		}

		for (int i = 0; i < _baseSizeCB.getModel().getNumEntries(); i++) {
			if (_baseSizeCB.getModel().getEntry(i).getWidth() == entry.getBase().getWidth()
					&& _baseSizeCB.getModel().getEntry(i).getHeight() == entry.getBase().getHeight())
				_baseSizeCB.setSelected(i);
		}
	}

	private void initComboBoxes() {
		SimpleChangableListModel<TroopType> TroopTypeModel = new SimpleChangableListModel<TroopType>();
		for (TroopType t : TroopType.values()) {
			TroopTypeModel.addElement(t);
		}

		SimpleChangableListModel<ModelBase> BaseSizeModel = new SimpleChangableListModel<ModelBase>();
		for (ModelBase mb : ModelBase.values()) {
			BaseSizeModel.addElement(mb);
		}

		SimpleChangableListModel<Weapon> WeaponsModel = new SimpleChangableListModel<Weapon>();
		for (Weapon w : Weapon.values()) {
			WeaponsModel.addElement(w);
		}
		_troopTypeCB.setModel(TroopTypeModel);
		_baseSizeCB.setModel(BaseSizeModel);
		_weaponsCB.setModel(WeaponsModel);
	}

	private void accept() {
		_player.removeAllUnits();
		for (int i = 0; i < _unitsListBox.getModel().getNumEntries(); i++) {
			_player.addUnit(_unitsListBox.getModel().getEntry(i));
		}
		_mMS.enterNewGameMenu();
	}

	private void cancel() throws IllegalStateException {

		_mMS.enterNewGameMenu();
	}

	private void add() {
		add(new Unit());
	}

	private void add(Unit unit) {
		SimpleChangableListModel<Unit> UnitModel = (SimpleChangableListModel<Unit>) _unitsListBox.getModel();

		UnitModel.addElement(unit);
		_unitsListBox.setSelected(_unitsListBox.getNumEntries() - 1);

	}

	private void remove() {
		SimpleChangableListModel<Unit> UnitModel = (SimpleChangableListModel<Unit>) _unitsListBox.getModel();
		int SelectedIndex = _unitsListBox.getSelected();
		if (SelectedIndex > -1)
			UnitModel.removeElement(SelectedIndex);
		if (UnitModel.getNumEntries() > 0) {
			if (SelectedIndex > 0) {
				_unitsListBox.setSelected(SelectedIndex - 1);
			} else if (SelectedIndex == 0)
				_unitsListBox.setSelected(SelectedIndex);
		}
		if (_unitsListBox.getSelected() == -1)
			_unitPropertiesPanel.setEnabled(false);
	}

	@Override
	public void update() {

	}

	public void init() {
		_nameLabel.setText(_player.getName() + "(" + _player.getArmyName() + ")");
	}

	public void layout() {
		setSize(900, 600);
		_unitsListBox.setMinSize(_unitsListBox.getWidth(), 300);

		_unitPropertiesPanel.adjustSize();
		_manageArmyPanel.adjustSize();
		_manageArmyPanel.setPosition(getInnerX() + (getInnerWidth() - _manageArmyPanel.getWidth()) / 2,
				getInnerY() + (getInnerHeight() - _manageArmyPanel.getHeight()) / 2);
	}

	public void loadUnits() {
		for (Unit unit : Game.getMatch().getPlayer1().getUnits()) {
			add(unit);
		}
	}
}
